package com.zlp.spring.aop.aop;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Aop 日志切面
 * @date: 2022/2/25 11:11
 */
@Aspect
@Component
public class AopLog {

    @Pointcut("execution(* com.zlp.spring.aop.service..*.*(..) )")
    public void pointCut() { }

    //    方法执行前通知
    @Before("pointCut()")
    public void beforeLog(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        System.out.println("前置通知 Before 日志记录... 参数为：" + Arrays.asList(args));
    }

    //    方法执行完后通知
    @After("pointCut()")
    public void afterLog(JoinPoint joinPoint) {
        System.out.println("后置通知 After 日志记录");
    }

    //    执行成功后通知
    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturningLog(JoinPoint joinPoint,Object result) {
        System.out.println("执行成功后通知 AfterReturning 日志记录,结果为：" + result);
    }

    //    抛出异常后通知
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception) {

        System.out.println(joinPoint.getSignature().getName() + "抛出异常后通知 AfterThrowing... 异常信息：" + exception);
    }

    //    环绕通知
//    @Around("pointCut()")
    public Object aroundLog(ProceedingJoinPoint joinpoint) throws Exception {

//        // 获取被增强的目标对象，然后获取目标对象的class
//        Class<?> targetClass = joinpoint.getTarget().getClass();
//        System.out.println("执行Around，被增强的目标类为：" + targetClass);
//        // 方法名称
//        String methodName = joinpoint.getSignature().getName();
//        System.out.println("执行Around，目标方法名称为：" + methodName);
//        // 目标方法的参数类型
//        Class[] parameterTypes = ((MethodSignature) joinpoint.getSignature()).getParameterTypes();
//        // 目标方法的入参
//        Object[] args = joinpoint.getArgs();
//        System.out.println("执行Around，方法入参为：" + Arrays.toString(args));

        Object result = null;
        try {
            System.out.println("环绕通知 Before 日志记录");
            long start = System.currentTimeMillis();
            //有返回参数 则需返回值
            result =  joinpoint.proceed();
//            long end = System.currentTimeMillis();
//            System.out.println("总共执行时长" + (end - start) + " 毫秒");
            System.out.println("环绕通知 After 日志记录");
        } catch (Throwable t) {
//            System.out.println("出现错误"+t.getMessage());
            throw new Exception("出现错误"+t.getMessage());
        }
        return result;
    }


}
